<template>
  <div ref="container" class="scene-container"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from "vue";
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import * as dat from "dat.gui";
// import { useMouse } from "@vueuse/core";

onMounted(() => {});
/**
 * 认识point
 */
// 给当前组件定义名称
defineOptions({
  name: "ThreeScene",
});

const container = ref<HTMLElement>();
let scene: THREE.Scene;
let camera: THREE.PerspectiveCamera;
let renderer: THREE.WebGLRenderer;
let controls: OrbitControls;
let sphere: THREE.Mesh;
let plane: THREE.Mesh;
let spotLight: THREE.SpotLight;
let smallBall: THREE.Mesh;
let points: THREE.Points;
//设置时钟
let clock = new THREE.Clock();
let geometry: THREE.BufferGeometry;
let material: THREE.PointsMaterial;
const params = {
  count: 10000,
  size: 0.3,
  radius: 10,
  branch: 5,
  color: "#ff6030",
  rotateScale: 0.3,
  asideColor: "#ffff00",
};
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load(
  "/textures/PNG (Black background)/circle_05.png"
);

const generateGalaxy = (scene: THREE.Scene) => {
  //生成顶点
  geometry = new THREE.BufferGeometry();
  //随机生成位置
  const positions = new Float32Array(params.count * 3);
  //设置顶点颜色
  const colors = new Float32Array(params.count * 3);
  //循环生成点
  for (let i = 0; i < params.count; i++) {
    //当前的点应该在哪一条分支的角度
    const branchAngle = (i % params.branch) * ((Math.PI * 2) / params.branch); //计算当前点在哪一条分支的角度
    //当前点距离圆心的距离
    const distance = Math.random() * params.radius * Math.pow(Math.random(), 3); //随机生成距离

    const current = i * 3;
    const randomX =
      (Math.pow(Math.random() * 2 - 1, 3) * (params.radius - distance)) / 5;
    const randomY =
      (Math.pow(Math.random() * 2 - 1, 3) * (params.radius - distance)) / 5;
    const randomZ =
      (Math.pow(Math.random() * 2 - 1, 3) * (params.radius - distance)) / 5;
    // const randomX = Math.pow(Math.random() * 2 - 1, 3) * distance;
    // const randomY = Math.pow(Math.random() * 2 - 1, 3) * distance;
    // const randomZ = Math.pow(Math.random() * 2 - 1, 3) * distance;
    positions[current] =
      Math.cos(branchAngle + distance * params.rotateScale) * distance +
      randomX; //计算当前点在哪一条分支的角度
    positions[current + 1] = 0 + randomY; //y轴为0
    positions[current + 2] =
      Math.sin(branchAngle + distance * params.rotateScale) * distance +
      randomZ; //计算当前点在哪一条分支的角度
    //混合颜色，形成渐变色
    // const mixColor = new Float32Array(params.count * 3);
    const centerColor = new THREE.Color(params.color); //中心颜色
    const asideColor = new THREE.Color(params.asideColor); //边缘颜色
    const mixColor = centerColor.lerp(asideColor, distance / params.radius);
    colors[current] = mixColor.r;
    colors[current + 1] = mixColor.g;
    colors[current + 2] = mixColor.b;
  }
  geometry.setAttribute("position", new THREE.BufferAttribute(positions, 3));
  geometry.setAttribute("color", new THREE.BufferAttribute(colors, 3));
  //设置点材质
  material = new THREE.PointsMaterial({
    size: params.size,
    // color: new THREE.Color(params.color),
    sizeAttenuation: true,
    depthWrite: false,
    blending: THREE.AdditiveBlending,
    map: texture,
    transparent: true,
    alphaMap: texture,
    vertexColors: true,
  });
  points = new THREE.Points(geometry, material);
  scene.add(points);
};
// 初始化场景
const initScene = () => {
  // 创建场景
  scene = new THREE.Scene();
  scene.background = new THREE.Color(0x000000); // 设置较暗的背景色
  // 创建相机
  camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );
  camera.position.set(0, 20, 0);
  scene.add(camera);
  //创建1000个立方体
  const cubeGeometry = new THREE.BoxGeometry(1, 1, 1);
  const cubeMaterial = new THREE.MeshBasicMaterial({ wireframe: true });
  const redMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });
  const cubeArr = [];
  for (let i = -5; i < 5; i++) {
    for (let j = -5; j < 5; j++) {
      for (let z = -5; z < 5; z++) {
        const cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
        cube.position.set(i * 1, j * 1, z * 1);
        scene.add(cube);
        cubeArr.push(cube);
      }
    }
  }
  //创建投射光线对象
  const raycaster = new THREE.Raycaster();
  //鼠标的位置对象
  const mouse = new THREE.Vector2();
  //监听鼠标移动
  window.addEventListener("mousemove", (event) => {
    mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
    mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
    raycaster.setFromCamera(mouse, camera);
    let result = raycaster.intersectObjects(cubeArr);
    if (result.length > 0) {
      result[0].object.material = redMaterial;
      // result.forEach((intersect) => {
      //   intersect.object.material = redMaterial;
      // });
    }
    // intersects.forEach((intersect) => {
    //   intersect.object.material=redMaterial;
    // });
  });

  // generateGalaxy(scene);
  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  renderer.shadowMap.enabled = true; // 开启阴影
  renderer.shadowMap.type = THREE.PCFSoftShadowMap;
  container.value?.appendChild(renderer.domElement);
  // 添加坐标轴辅助
  const axesHelper = new THREE.AxesHelper(10);
  scene.add(axesHelper);

  // 添加聚光灯辅助
  // const spotLightHelper = new THREE.SpotLightHelper(spotLight);
  // scene.add(spotLightHelper);

  // 添加轨道控制器
  controls = new OrbitControls(camera, renderer.domElement);
  controls.enableDamping = true;
  controls.dampingFactor = 0.5;

  // 开始动画循环
  animate();
};

// 动画循环函数
const animate = () => {
  let time = clock.getElapsedTime();
  // points.rotation.x = time * 0.2;
  // 以y轴为中心旋转
  // points.rotation.y = -time * 100;
  requestAnimationFrame(animate);
  controls.update();
  renderer.render(scene, camera);
  // console.log("Rendering frame..."); // 调试信息
};

// 处理窗口大小变化
const handleResize = () => {
  if (camera && renderer) {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
  }
};

// 组件挂载时初始化
onMounted(() => {
  initScene();
  window.addEventListener("resize", handleResize);
});

// 组件卸载时清理
onBeforeUnmount(() => {
  window.removeEventListener("resize", handleResize);
});
</script>

<style scoped>
.scene-container {
  width: 100%;
  height: 100vh;
  overflow: hidden;
}
</style>
